/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Oct 25, 2004
*
* @author Fabio Zadrozny
*/
package org.python.pydev.builder.todo;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.python.pydev.builder.PyDevBuilderVisitor;
import org.python.pydev.builder.PydevMarkerUtils;
import org.python.pydev.builder.PydevMarkerUtils.MarkerInfo;
import org.python.pydev.core.callbacks.ICallback0;
import org.python.pydev.core.docutils.ParsingUtils;
import org.python.pydev.core.docutils.SyntaxErrorException;
import org.python.pydev.core.log.Log;
import org.python.pydev.logging.DebugSettings;
/**
* @author Fabio Zadrozny
*/
public class PyTodoVisitor extends PyDevBuilderVisitor {
/*
* (non-Javadoc)
*
* @see org.python.pydev.builder.PyDevBuilderVisitor#visitResource(org.eclipse.core.resources.IResource)
*/
@Override
public void visitChangedResource(IResource resource, ICallback0<IDocument> document, IProgressMonitor monitor) {
if (document != null) {
List<String> todoTags = PyTodoPrefPage.getTodoTags();
try {
if (!isResourceInPythonpathProjectSources(resource, this.getPythonNature(resource), false)) {
PydevMarkerUtils.removeMarkers(resource, IMarker.TASK);
return;
}
} catch (Exception e1) {
Log.log(e1);
return;
}
try {
PydevMarkerUtils.replaceMarkers(computeTodoMarkers(document.call(), todoTags), resource, IMarker.TASK,
false, monitor);
//timer.printDiff("Total time to put markers: "+lst.size());
} catch (Exception e) {
Log.log(e);
}
}
}
/**
* Computes the TODO markers available for this document.
* Considers only TODO flags in strings and comments.
*/
/*default*/List<MarkerInfo> computeTodoMarkers(IDocument document, List<String> todoTags)
throws BadLocationException {
List<PydevMarkerUtils.MarkerInfo> lst = new ArrayList<PydevMarkerUtils.MarkerInfo>();
if (todoTags.size() > 0) {
ParsingUtils utils = ParsingUtils.create(document);
int len = utils.len();
try {
for (int i = 0; i < len; i++) {
char c = utils.charAt(i);
switch (c) {
case '\'':
case '\"':
int j = utils.eatLiterals(null, i);
check(i, j, document, lst, todoTags);
i = j;
break;
case '#':
j = utils.eatComments(null, i);
check(i, j, document, lst, todoTags);
i = j;
break;
}
}
} catch (BadLocationException e) {
//ignore (if document changed in the iteration).
} catch (SyntaxErrorException e) {
Log.log(e); //Should not happen!
}
if (DebugSettings.DEBUG_ANALYSIS_REQUESTS) {
Log.toLogFile(this, "Adding todo markers");
}
}
return lst;
}
/**
* Checks a partition of a document for todo tags (filling lst with the markers to be created).
*/
private void check(int i, int j, IDocument document, List<MarkerInfo> lst, List<String> todoTags)
throws BadLocationException {
String tok = document.get(i, j - i);
int index;
HashSet<Integer> lines = new HashSet<Integer>();
for (String element : todoTags) {
if (element.length() == 0) {
continue;
}
int start = 0;
while ((index = tok.indexOf(element, start)) != -1) {
start = index + element.length();
int absoluteStart = i + index;
int line = document.getLineOfOffset(absoluteStart);
if (lines.contains(line)) {
//Only 1 TASK per line!
continue;
} else {
lines.add(line);
}
String message = tok.substring(index).trim();
String markerType = IMarker.TASK;
int severity = IMarker.SEVERITY_WARNING;
boolean userEditable = false;
boolean isTransient = false;
int absoluteEnd = absoluteStart + message.length();
Map<String, Object> additionalInfo = null;
MarkerInfo markerInfo = new PydevMarkerUtils.MarkerInfo(document, message, markerType, severity,
userEditable, isTransient, line, absoluteStart, absoluteEnd, additionalInfo);
lst.add(markerInfo);
}
}
}
/**
* @see org.python.pydev.builder.PyDevBuilderVisitor#visitRemovedResource(org.eclipse.core.resources.IResource, org.eclipse.jface.text.IDocument)
*/
@Override
public void visitRemovedResource(IResource resource, ICallback0<IDocument> document, IProgressMonitor monitor) {
}
}